/*
 * Unidata Platform Community Edition
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 * This file is part of the Unidata Platform Community Edition software.
 *
 * Unidata Platform Community Edition is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Unidata Platform Community Edition is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
 */

package org.unidata.mdm.meta.context;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

import org.unidata.mdm.core.context.AbstractModelGetContext;
import org.unidata.mdm.core.service.segments.ModelGetStartExecutor;
import org.unidata.mdm.meta.configuration.TypeIds;
import org.unidata.mdm.meta.util.ModelUtils;
import org.unidata.mdm.system.context.DraftAwareContext;

/**
 * @author Mikhail Mikhailov on Nov 28, 2019
 */
public class GetDataModelContext extends AbstractModelGetContext implements DraftAwareContext {
    /**
     * GSVUID.
     */
    private static final long serialVersionUID = -6245429588435518790L;
    /**
     * A possibly set draft id.
     */
    private final Long draftId;
    /**
     * A possibly set parent draft id.
     */
    private final Long parentDraftId;
    /**
     * Requested group ids.
     */
    private final List<String> entityGroupIds;
    /**
     * Requested entity ids.
     */
    private final List<String> entityIds;
    /**
     * Requested nested entity ids.
     */
    private final List<String> nestedEntityIds;
    /**
     * Requested lookup ids.
     */
    private final List<String> lookupIds;
    /**
     * Requested relation ids.
     */
    private final List<String> relationIds;
    /**
     * Constructor.
     * @param b the builder.
     */
    private GetDataModelContext(GetDataModelContextBuilder b) {

        super(b);
        this.entityGroupIds = Objects.isNull(b.entityGroupIds) ? Collections.emptyList() : b.entityGroupIds;
        this.entityIds = Objects.isNull(b.entityIds) ? Collections.emptyList() : b.entityIds;
        this.nestedEntityIds = Objects.isNull(b.nestedEntityIds) ? Collections.emptyList() : b.nestedEntityIds;
        this.lookupIds = Objects.isNull(b.lookupIds) ? Collections.emptyList() : b.lookupIds;
        this.relationIds = Objects.isNull(b.relationIds) ? Collections.emptyList() : b.relationIds;
        this.draftId = b.draftId;
        this.parentDraftId = b.parentDraftId;

        setFlag(MetaContextFlags.FLAG_REDUCED, b.reduced);
        setFlag(MetaContextFlags.FLAG_ALL_ENTITIES, b.allEntities);
        setFlag(MetaContextFlags.FLAG_ALL_NESTED_ENTITIES, b.allNestedEntities);
        setFlag(MetaContextFlags.FLAG_ALL_ENTITY_GROUPS, b.allEntityGroups);
        setFlag(MetaContextFlags.FLAG_FILLED_ENTITY_GROUPS, b.filledEntityGroups);
        setFlag(MetaContextFlags.FLAG_ALL_LOOKUPS, b.allLookups);
        setFlag(MetaContextFlags.FLAG_ALL_RELATIONS, b.allRelations);
        setFlag(MetaContextFlags.FLAG_ALL_FROM_RELATIONS, b.allFromRelations);
        setFlag(MetaContextFlags.FLAG_ALL_TO_RELATIONS, b.allToRelations);
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public Long getDraftId() {
        return draftId;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public Long getParentDraftId() {
        return parentDraftId;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public String getTypeId() {
        return TypeIds.DATA_MODEL;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public String getInstanceId() {
        // Data models are singletons per storage
        return ModelUtils.DEFAULT_MODEL_INSTANCE_ID;
    }
    /**
     * {@inheritDoc}
     */
    @Override
    public String getStartTypeId() {
        return ModelGetStartExecutor.SEGMENT_ID;
    }
    /**
     * Is a reduced info request?
     * @return reduced request state
     */
    public boolean isReduced() {
        return getFlag(MetaContextFlags.FLAG_REDUCED);
    }
    /**
     * All entities requested?
     * @return request state
     */
    public boolean isAllEntities() {
        return getFlag(MetaContextFlags.FLAG_ALL_ENTITIES);
    }
    /**
     * All netsed entities requested?
     * @return request state
     */
    public boolean isAllNestedEntities() {
        return getFlag(MetaContextFlags.FLAG_ALL_NESTED_ENTITIES);
    }
    /**
     * All entity groups requested?
     * @return request state
     */
    public boolean isAllEntityGroups() {
        return getFlag(MetaContextFlags.FLAG_ALL_ENTITY_GROUPS);
    }
    /**
     * Only filled entity groups with content requested?
     * @return request state
     */
    public boolean isFilledEntityGroups() {
        return getFlag(MetaContextFlags.FLAG_FILLED_ENTITY_GROUPS);
    }
    /**
     * All lookups requested?
     * @return request state
     */
    public boolean isAllLookups() {
        return getFlag(MetaContextFlags.FLAG_ALL_LOOKUPS);
    }
    /**
     * All relations requested?
     * @return request state
     */
    public boolean isAllRelations() {
        return getFlag(MetaContextFlags.FLAG_ALL_RELATIONS);
    }
    /**
     * All from relations requested?
     * @return request state
     */
    public boolean isAllFromRelations() {
        return getFlag(MetaContextFlags.FLAG_ALL_FROM_RELATIONS);
    }
    /**
     * All to relations requested?
     * @return request state
     */
    public boolean isAllToRelations() {
        return getFlag(MetaContextFlags.FLAG_ALL_TO_RELATIONS);
    }
    /**
     * @return the entityGroupIds
     */
    public List<String> getEntityGroupIds() {
        return entityGroupIds;
    }
    /**
     * @return the entityIds
     */
    public List<String> getEntityIds() {
        return entityIds;
    }
    /**
     * @return the nestedEntityIds
     */
    public List<String> getNestedEntityIds() {
        return nestedEntityIds;
    }
    /**
     * @return the lookupIds
     */
    public List<String> getLookupIds() {
        return lookupIds;
    }
    /**
     * @return the relationIds
     */
    public List<String> getRelationIds() {
        return relationIds;
    }
    /**
     * Gets a builder instance.
     * @return builder instance
     */
    public static GetDataModelContextBuilder builder() {
        return new GetDataModelContextBuilder();
    }
    /**
     * The builder for this context.
     * @author Mikhail Mikhailov on Nov 28, 2019
     */
    public static class GetDataModelContextBuilder extends AbstractModelGetContextBuilder<GetDataModelContextBuilder> {
        /**
         * Gather reduced set of information.
         */
        private boolean reduced;
        /**
         * Requested group ids.
         */
        private List<String> entityGroupIds;
        /**
         * All groups requested.
         */
        private boolean allEntityGroups;
        /**
         * Only filled (with content) groups requested.
         */
        private boolean filledEntityGroups;
        /**
         * Requested entity ids.
         */
        private List<String> entityIds;
        /**
         * All entities requested.
         */
        private boolean allEntities;
        /**
         * Requested nested entity ids.
         */
        private List<String> nestedEntityIds;
        /**
         * All entities requested.
         */
        private boolean allNestedEntities;
        /**
         * Requested lookup ids.
         */
        private List<String> lookupIds;
        /**
         * All lookups requested.
         */
        private boolean allLookups;
        /**
         * Requested relation ids.
         */
        private List<String> relationIds;
        /**
         * All relations requested.
         */
        private boolean allRelations;
        /**
         * All outgoing relations by entity(ies) as from side requested.
         */
        private boolean allFromRelations;
        /**
         * All incomming relations by entity(ies) as to side requested.
         */
        private boolean allToRelations;
        /**
         * The draft id.
         */
        private Long draftId;
        /**
         * The parent draft id.
         */
        private Long parentDraftId;
        /**
         * Constructor.
         */
        protected GetDataModelContextBuilder() {
            super();
        }
        /**
         * Sets draft id
         * @param draftId the draft id
         * @return self
         */
        public GetDataModelContextBuilder draftId(Long draftId) {
            this.draftId = draftId;
            return self();
        }
        /**
         * Sets parent draft id
         * @param parentDraftId the parent draft id
         * @return self
         */
        public GetDataModelContextBuilder parentDraftId(Long parentDraftId) {
            this.parentDraftId = parentDraftId;
            return self();
        }
        /**
         * @param reduced the reduced to set
         */
        public GetDataModelContextBuilder reduced(boolean reduced) {
            this.reduced = reduced;
            return self();
        }
        /**
         * @param entityGroupIds the entityGroupIds to set
         */
        public GetDataModelContextBuilder entityGroupIds(List<String> entityGroupIds) {
            this.entityGroupIds = entityGroupIds;
            return self();
        }
        /**
         * @param allEntityGroups the allEntityGroups to set
         */
        public GetDataModelContextBuilder allEntityGroups(boolean allEntityGroups) {
            this.allEntityGroups = allEntityGroups;
            return self();
        }
        /**
         * @param filledEntityGroups the filledEntityGroups to set
         */
        public GetDataModelContextBuilder filledEntityGroups(boolean filledEntityGroups) {
            this.filledEntityGroups = filledEntityGroups;
            return self();
        }
        /**
         * @param entityIds the entityIds to set
         */
        public GetDataModelContextBuilder entityIds(List<String> entityIds) {
            this.entityIds = entityIds;
            return self();
        }
        /**
         * @param allEntities the allEntities to set
         */
        public GetDataModelContextBuilder allEntities(boolean allEntities) {
            this.allEntities = allEntities;
            return self();
        }
        /**
         * @param nestedEntityIds the nestedEntityIds to set
         */
        public GetDataModelContextBuilder nestedEntityIds(List<String> nestedEntityIds) {
            this.nestedEntityIds = nestedEntityIds;
            return self();
        }
        /**
         * @param allNestedEntities the allNestedEntities to set
         */
        public GetDataModelContextBuilder allNestedEntities(boolean allNestedEntities) {
            this.allNestedEntities = allNestedEntities;
            return self();
        }
        /**
         * @param lookupIds the lookupIds to set
         */
        public GetDataModelContextBuilder lookupIds(List<String> lookupIds) {
            this.lookupIds = lookupIds;
            return self();
        }
        /**
         * @param allLookups the allLookups to set
         */
        public GetDataModelContextBuilder allLookups(boolean allLookups) {
            this.allLookups = allLookups;
            return self();
        }
        /**
         * @param relationIds the relationIds to set
         */
        public GetDataModelContextBuilder relationIds(List<String> relationIds) {
            this.relationIds = relationIds;
            return self();
        }
        /**
         * @param allRelations the allRelations to set
         */
        public GetDataModelContextBuilder allRelations(boolean allRelations) {
            this.allRelations = allRelations;
            return self();
        }
        /**
         * All outgoing relations by entity(ies) as from side requested.
         * @param allFromRelations the allFromRelations to set
         */
        public GetDataModelContextBuilder allFromRelations(boolean allFromRelations) {
            this.allFromRelations = allFromRelations;
            return self();
        }
        /**
         * All incomming relations by entity(ies) as to side requested.
         * @param allToRelations the allToRelations to set
         */
        public GetDataModelContextBuilder allToRelations(boolean allToRelations) {
            this.allToRelations = allToRelations;
            return self();
        }
        /**
         * {@inheritDoc}
         */
        @Override
        public GetDataModelContext build() {
            return new GetDataModelContext(this);
        }
    }
}
